package bitset

import "fmt"

type BitSet struct {
	data    []byte
	bitSize uint
}

func New(bitSize uint) *BitSet {
	return &BitSet{
		bitSize: bitSize,
		data:    make([]byte, (bitSize+7)/8),
	}
}

func (b *BitSet) Set(index uint) {
	b.data[index/8] |= 1 << (index % 8)
}

func (b *BitSet) SetTo(index uint, value bool) {
	if value {
		b.Set(index)
	} else {
		b.Clear(index)
	}
}

func (b *BitSet) Clear(index uint) {
	b.data[index/8] &= ^(1 << (index % 8))
}

func (b *BitSet) Test(index uint) bool {
	return b.data[index/8]&(1<<(index%8)) != 0
}

func (b *BitSet) Size() uint {
	return b.bitSize
}

func (b *BitSet) Bytes() []byte {
	return b.data
}

func (b *BitSet) SetByteValue(index uint, value byte) {
	b.data[index] = value
}

func (b *BitSet) GetByteValue(index uint) byte {
	return b.data[index]
}

func (b *BitSet) SetBytesValue(values []byte) {
	b.data = values
}

func (b *BitSet) SetBytesCopy(values []byte) {
	b.data = make([]byte, len(values))
	copy(b.data, values)
}

func (b *BitSet) BytesCopy(values []byte) {
	copy(values, b.data)
}

func (b *BitSet) BytesCopyFrom(values []byte) {
	copy(b.data, values)
}

func (b *BitSet) String() string {
	return fmt.Sprintf("%b", b.data)
}
